package cn.iocoder.yudao.module.mqtt.service.device;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.mqtt.controller.admin.device.vo.DevicePageReqVO;
import cn.iocoder.yudao.module.mqtt.controller.admin.device.vo.DeviceSaveReqVO;
import cn.iocoder.yudao.module.mqtt.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.mqtt.dal.dataobject.devicelatestflow.DeviceLatestFlowDO;
import cn.iocoder.yudao.module.mqtt.dal.mysql.device.DeviceMapper;
import cn.iocoder.yudao.module.mqtt.dal.mysql.devicelatest.DeviceLatestFlowMapper;
import cn.iocoder.yudao.module.mqtt.framework.config.MqttProperties;
import cn.iocoder.yudao.module.mqtt.util.MyFileUtil;
import cn.iocoder.yudao.module.mqtt.util.QRCodeUtil;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mqtt.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;

/**
 * IoT 设备 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class DeviceServiceImpl implements DeviceService {

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private DeviceLatestFlowMapper deviceLatestMapper;

    @Autowired
    private MqttProperties mqttProperties;

    @Resource
    private PermissionService permissionService;

    @Override
    public Long createDevice(DeviceSaveReqVO createReqVO) {
        if (createReqVO.getDeviceKey() == null) {
            throw new ServiceException(new ErrorCode(10001, "设备KEY不能为空"));
        }
        createReqVO.setDataSource("0");//系统
        // 插入
        DeviceDO device = BeanUtils.toBean(createReqVO, DeviceDO.class);
        deviceMapper.insert(device);

//        DeviceLatestFlowDO lastest = new DeviceLatestFlowDO();
//        lastest.setDeviceKey(device.getDeviceKey());
//        lastest.setPayloadWd("");
//        lastest.setPayloadZd("");
//        lastest.setPayloadYl("");
//        lastest.setPayloadPh("");
//        deviceLatestMapper.insert(lastest);
        // 返回
        return device.getId();
    }

    @Override
    public void updateDevice(DeviceSaveReqVO updateReqVO) {
        // 校验存在
        validateDeviceExists(updateReqVO.getId());



        // 更新
        DeviceDO updateObj = BeanUtils.toBean(updateReqVO, DeviceDO.class);
        deviceMapper.updateById(updateObj);
    }

    @Override
    public Long createLis(DeviceDO deviceDO) {
        deviceMapper.insert(deviceDO);

        DeviceLatestFlowDO deviceLatest = new DeviceLatestFlowDO();
        deviceLatest.setId(deviceDO.getId());
        deviceLatest.setDeviceKey(deviceDO.getDeviceKey());
        deviceLatest.setGatewayId(deviceDO.getDeviceKey());
        deviceLatest.setDeviceId(deviceDO.getId());
        deviceLatest.setCreator("SYS");
        deviceLatestMapper.insertOrUpdate(deviceLatest);
        return deviceDO.getId();
    }

    @Override
    public void updateLis(DeviceDO deviceDO) {
        // 更新
        DeviceDO updateObj = BeanUtils.toBean(deviceDO, DeviceDO.class);
        deviceMapper.update(updateObj ,
                new QueryWrapper<DeviceDO>().eq("device_name",deviceDO.getDeviceName()));

        DeviceLatestFlowDO deviceLatest = new DeviceLatestFlowDO();
        deviceLatest.setId(deviceDO.getId());
        deviceLatest.setDeviceKey(deviceDO.getDeviceKey());
        deviceLatest.setGatewayId(deviceDO.getDeviceKey());
        deviceLatest.setDeviceId(deviceDO.getId());
        deviceLatest.setCreator("SYS");
        deviceLatest.setDeviceName(deviceDO.getDeviceName());
        deviceLatest.setLisDay("0");
        deviceLatestMapper.insertOrUpdate(deviceLatest);
    }

    @Override
    public void deleteDevice(Long id) {
        // 校验存在
        validateDeviceExists(id);
        // 删除
        deviceMapper.deleteById(id);
    }

    @Override
    public void deleteDeviceListByIds(List<Long> ids) {
        // 校验存在
        validateDeviceExists(ids);
        // 删除
        deviceMapper.deleteByIds(ids);
    }

    private void validateDeviceExists(List<Long> ids) {
        List<DeviceDO> list = deviceMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(DEVICE_NOT_EXISTS);
        }
    }

    private void validateDeviceExists(Long id) {
        if (deviceMapper.selectById(id) == null) {
            throw exception(DEVICE_NOT_EXISTS);
        }
    }

    @Override
    public DeviceDO getDevice(Long id) {
        return deviceMapper.selectById(id);
    }

    @Override
    public PageResult<DeviceDO> getDevicePage(DevicePageReqVO pageReqVO) {
        // 解析 ids
        List<Long> idList = parseIds(pageReqVO.getIds());

        // 构建查询条件
        LambdaQueryWrapper<DeviceDO> queryWrapper = new LambdaQueryWrapper<DeviceDO>()
                .like(StringUtils.isNotBlank(pageReqVO.getDeviceName()),
                        DeviceDO::getDeviceName, pageReqVO.getDeviceName())
                .eq(ObjectUtil.isNotNull(pageReqVO.getDeviceType()),
                        DeviceDO::getDeviceType, pageReqVO.getDeviceType())
                .and(ObjectUtil.isNotEmpty(idList), wrapper -> {
                    if (BooleanUtil.isTrue(pageReqVO.getExcludeAssigned())) {
                        wrapper.notIn(DeviceDO::getId, idList);
                    } else {
                        wrapper.in(DeviceDO::getId, idList);
                    }
                });

        // 执行分页查询
        Page<DeviceDO> resultPage = deviceMapper.selectPage(
                Page.of(pageReqVO.getPageNo(), pageReqVO.getPageSize()),
                queryWrapper
        );

        return new PageResult<>(resultPage.getRecords(), resultPage.getTotal());
    }

    /**
     * 解析ID字符串为List
     */
    private List<Long> parseIds(String idsStr) {
        if (StringUtils.isBlank(idsStr)) {
            return Collections.emptyList();
        }

        return Arrays.stream(idsStr.split(","))
                .map(String::trim)
                .filter(StringUtils::isNotBlank)
                .map(Long::valueOf)
                .collect(Collectors.toList());
    }

    @Override
    public PageResult<DeviceDO> getDevicePermissionPage(DevicePageReqVO pageReqVO) {
        Set<Long> roleIdSet = permissionService.getUserRoleIdListByUserId(SecurityFrameworkUtils.getLoginUserId());
        boolean exists = roleIdSet.contains(1L) || roleIdSet.contains(3L);
        if (!exists) {
            List<Long> idList = deviceMapper.selectByDeviceId(SecurityFrameworkUtils.getLoginUserId());
            pageReqVO.setIdList(idList);
        }
        return deviceMapper.selectPage(pageReqVO);
    }

    @Override
    public List<DeviceDO> getList(DeviceDO ddo) {
        return deviceMapper.selectList(ddo);
    }

    @Override
    public void updateDeviceIsUpload(Long deviceId) {
        DeviceDO deviceDO = deviceMapper.selectById(deviceId);
        deviceDO.setIsUpload(deviceDO.getIsUpload().equals("0")?"1":"0");
        deviceDO.setUpdateTime(LocalDateTime.now());
        deviceMapper.updateById(deviceDO);
    }

    @Override
    public String updateUpload(MultipartFile file, Long deviceId) {
        String path = mqttProperties.getUpload();
        if (ObjUtil.isNotEmpty(deviceId) && 0 != deviceId) {
            DeviceDO deviceDO = deviceMapper.selectById(deviceId);
            if (ObjUtil.isNotEmpty(deviceDO.getPicUrl())) {
                String deletepath = path + File.separator + deviceDO.getPicUrl();
                File deleteFile = new File(deletepath);
                deleteFile.delete();
            }

            DeviceDO deviceDO2 = new DeviceDO();
            deviceDO2.setId(deviceId);
            deviceDO2.setPicUrl(file.getOriginalFilename());
            deviceMapper.updateById(deviceDO2);
        }

        File uploadDir = new File(path);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }

        String filename = file.getOriginalFilename();
        String newName = deviceId + filename.substring(filename.lastIndexOf("."));
        MyFileUtil.saveFile(file, path + File.separator + newName);
        // 返回
        return newName;
    }

    /**
     * 获取或生成设备的 deviceKey（UUID）
     */
    @Transactional
    public String getOrCreateDeviceKey(Long deviceId) {
        // 1. 查询设备
        DeviceDO device = deviceMapper.selectById(deviceId);
        if (device == null) {
            throw new ServiceException(new ErrorCode(1, "设备不存在，ID：" + deviceId));
        }

        // 2. 如果 deviceKey 已存在，直接返回
        if (StringUtils.isNotBlank(device.getDeviceKey()) && StringUtils.isNotBlank(device.getGatewayId().toString())) {
            String data = String.format(
                    "{\"deviceKey\":\"%s\",\"devSN\":\"%s\"}",
                    device.getDeviceKey(),
                    device.getGatewayId()
            );
            return data;
        }

        // 3. 否则生成新的 12 位 UUID 作为 deviceKey
        String newDeviceKey = QRCodeUtil.generate12DigitUUID();
        String data = String.format(
                "{\"deviceKey\":\"%s\",\"devSN\":\"%s\"}",
                newDeviceKey,
                device.getGatewayId()
        );
        // 4. 更新到数据库
        DeviceDO update = new DeviceDO();
        update.setId(deviceId);
        update.setDeviceKey(newDeviceKey);

        int updated = deviceMapper.updateById(update);
        if (updated != 1) {
            throw new ServiceException(new ErrorCode(2, "更新 deviceKey 失败"));
        }

        return data;
    }

    @Override
    public String saveByMini(MultipartFile file, DeviceSaveReqVO saveReqVO) {
        if (saveReqVO.getDeviceKey() == null) {
            throw new ServiceException(new ErrorCode(10001, "设备KEY不能为空"));
        }
        String path = mqttProperties.getUpload();

        DeviceDO deviceDO = new DeviceDO();
        BeanUtils.copyProperties(saveReqVO, deviceDO);
        deviceDO.setPicUrl(file.getOriginalFilename());
        deviceDO.setDataSource("0");
        deviceMapper.insert(deviceDO);

        String filename = file.getOriginalFilename();
        deviceDO.setPicUrl(deviceDO.getId() + filename.substring(filename.lastIndexOf(".")));
        deviceMapper.updateById(deviceDO);

//        DeviceLatestFlowDO lastest = new DeviceLatestFlowDO();
//        lastest.setDeviceKey(saveReqVO.getDeviceKey());
//        lastest.setPayloadWd("");
//        lastest.setPayloadZd("");
//        lastest.setPayloadYl("");
//        lastest.setPayloadPh("");
//        deviceLatestMapper.insert(lastest);
        // 返回
        File uploadDir = new File(path);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }
        String newName = deviceDO.getId() + filename.substring(filename.lastIndexOf("."));
        MyFileUtil.saveFile(file, path + File.separator + newName);
        return deviceDO.getId() + "";
    }

    @Override
    public Long getCountBySiteName(String siteName) {
        QueryWrapper<DeviceDO> queryWrapper = new QueryWrapper<DeviceDO>();
        queryWrapper.eq("device_name", siteName);
        return deviceMapper.selectCount(queryWrapper);
    }

    @Override
    public Map<String, DeviceDO> getAllList() {
        List<DeviceDO> list = deviceMapper.selectList(); // 获取所有设备列表
        if (list == null || list.isEmpty()) {
            return new HashMap<>(); // 返回空的 HashMap
        }
        // 使用 for 循环将 deviceName 作为 key，DeviceDO 对象作为 value
        Map<String, DeviceDO> resultMap = new HashMap<>();
        for (DeviceDO device : list) {
            if (device.getDeviceName() != null) { // 避免 key 为 null
                resultMap.put(device.getDeviceName(), device);
            }
        }

        return resultMap;
    }

    @Override
    public  List<DeviceDO> selectList() {
        List<DeviceDO> list = deviceMapper.selectList(); // 获取所有设备列表
        return list;
    }


    public static void main(String[] args) {
        System.out.println("1.jpg".substring("1.jpg".lastIndexOf(".")));
    }
}